/*  CryptoServer - secure online voting server
    Copyright (C) 2004, 2005, 2006  The Adder Team

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

/**
 * @file Database.cc
 * Interface of the Database class.
 */

#include <stdexcept>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <vector>
#include <string>
#include <libadder/PublicKey.h>
#include <libadder/Vote.h>
#include <libadder/exceptions.h>
#include <iosfwd>

#include "exceptions.h"
#include "misc.h"
#include "Polynomial.h"

#include "Database.hh"
#include "Options.hh"
#include "Utilities.hh"
#include "DecryptionHandler.hh"


/**
 * Constructor.
 */
Database::Database()
: procedure("\0"), user(""), is_authority(false), db(NULL)
{}

/**
 * Destructor.
 */
Database::~Database()
{
}

/**
 * Forms a connection to the database
 *
 * @param dbname the name of the database
 * @param host the hostname of the database server
 * @param user the username of the database user
 * @param password the password of the database server
 * @param port the port of the database server
 * @return true if successful or false otherwise
 */
bool Database::open(std::string dbname, std::string host,
                    std::string user, std::string password,
                    int port)
{
    int rv;

    sqlite3_initialize();   /* initialize the SQLite library */
    if( (rv = sqlite3_open(dbname.c_str(), &db)) != SQLITE_OK ) {
        std::cerr << "ERROR: error opening database. Error Code: " << rv << std::endl;
        return false;
    }

    DEBUG(("DEBUG: Connecting to database (%s, %s, %s)\n", dbname.c_str(), host.c_str(), user.c_str()));

    return true;
}

/**
 * Closes the database connection.
 */
void Database::close()
{
    int rv;

    /* close database */
    if( (rv = sqlite3_close(db)) != SQLITE_OK ) {
        std::cerr << "Error closing database. Error Code: " << rv << std::endl;
    } else {
        DEBUG(("DEBUG: Database closed successfully.\n"));
    }

    /* release allocated resources */
    sqlite3_shutdown();
}


/**
 * Determines if a user_id/password pair is authentic.
 * @param user_id the user_id.
 * @param password the password.
 * @param authority will be set to the value of the is_authority column.
 * @param session_id will be set to the value of the session_id.
 * @return @b true if the pair is authentic, @b false otherwise.
 */
bool Database::authenticate(std::string user_id, std::string password,
                            std::string &authority, std::string &session_id,
                            std::string procedure)
{
    DEBUG(("DEBUG: Authenticating(1) %s...\n", user_id.c_str()));

    int rv, idx;
    std::string db_password, user_password, db_salt;

    /* retrieve user's password */
    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db, "SELECT password FROM users WHERE user_id = :uid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        db_password = (char*)sqlite3_column_text(stmt, 0);
    } else {
        Assert<Errors::Baduser> (rv != SQLITE_DONE);
    }

    sqlite3_finalize(stmt);

    /* retrieve user's salt */
    stmt = NULL;
    sqlite3_prepare_v2(db, "SELECT salt FROM users WHERE user_id = :uid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        db_salt = (char*)sqlite3_column_text(stmt, 0);
    } else {
        DEBUG(("ERROR: Error retrieving salt at authentication\n"));
    }

    //user_password = adder::sha1(password + db_salt);
    user_password = password;   // FIXME: adder::sha1 is broken
    //FIXME: remove this from the log once it works
    //DEBUG(("DEBUG: real password = %s, db password = %s\n", user_password.c_str(), db_password.c_str()));

    Assert<Errors::Baduser> (user_password == db_password);

    sqlite3_finalize(stmt);

    /* check if user is an authority */
    stmt = NULL;
    sqlite3_prepare_v2(db, 
            "SELECT * FROM is_authority WHERE user_id = :uid AND proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_ROW )
        std::cerr << "User not an authority." << std::endl;

    authority = (rv == SQLITE_ROW) ? "1" : "0";
    is_authority = (rv == SQLITE_ROW) ? true : false;

    sqlite3_finalize(stmt);

    try {
        session_id = create_session_id(user_id);
    } catch (...) {
        std::cerr << "Error setting session id" << std::endl;
    }

    if (!is_authority) {
        switch (get_stage(procedure)) {
            case STAGE_WAITKEYS:  // User is not an authority, and stage is auth-only.
            case STAGE_WAITPOLYNOMIAL:
            case STAGE_WAITGETPRIVKEYS:
            case STAGE_WAITDECRYPT:
                throw Errors::Badstage();
                break;
            default:
                set_user(user_id);
                return true;
        }
    } else {
        set_user(user_id);
        return true;
    }

}

/**
 * Determines if session_id is valid (i.e. if the user is logged in).
 * @param session_id the session_id.
 * @param user_id will be set to the value of the user_id.
 * @param authority will be set to the value of the is_authority column.
 * @return @b true if the pair is authentic, @b false otherwise.
 */
bool Database::authenticate(std::string session_id, std::string &user_id,
                            std::string &authority, std::string procedure)
{
     DEBUG(("DEBUG: Authenticating %s...\n", user_id.c_str()));
     int idx, rv, delta_t;

     sqlite3_stmt *stmt = NULL;
     sqlite3_prepare_v2(db,
             "SELECT user_id, strftime('%Y%m%d%H%M%S', 'now', 'localtime') - session_start AS delta_t FROM users WHERE session_id = :sid",
             -1, &stmt, NULL);
     idx = sqlite3_bind_parameter_index(stmt, ":sid");
     sqlite3_bind_text(stmt, idx, session_id.c_str(), -1, SQLITE_STATIC);

     if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        user_id = (char*)sqlite3_column_text(stmt, 0);
        delta_t = sqlite3_column_int(stmt, 1);
     } else {
        Assert<Errors::Baduser> (rv == SQLITE_ROW);
     }
     Assert<Errors::Badsession> (delta_t <= OPTIONS->session_time_limit);

     set_user(user_id);


     sqlite3_finalize(stmt);

     stmt = NULL;

     sqlite3_prepare_v2(db,
             "SELECT * FROM is_authority WHERE user_id = :uid AND proc_id = :procid",
             -1, &stmt, NULL);
     idx = sqlite3_bind_parameter_index(stmt, ":uid");
     sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

     idx = sqlite3_bind_parameter_index(stmt, ":procid");
     sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    rv = sqlite3_step(stmt);

    authority = (rv == SQLITE_ROW) ? "1" : "0";
    is_authority = (rv == SQLITE_ROW) ? true : false;

    sqlite3_finalize(stmt);

    return true;
}


/**
 * Create a unique session id for a user and store it in the database.
 * @param user_id the user_id.
 * @return the session id.
 */
std::string Database::create_session_id(std::string user_id)
{
    std::string session_id = user_id;
    int rv, idx;

    session_id.append(ltoa(time(NULL)));
    srand(time(NULL));

    session_id.append(ltoa(rand()));
    session_id = adder::sha1(session_id);
    std::cout << "\nsession_id is :" << session_id << std::endl;
    /*
     * FIXME: Why are we putting the session id in the database?
     * This value should not be public, and should not be needed by the db.
     */
    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db, 
            "UPDATE users SET session_id = :sid, session_start = strftime('%Y%m%d%H%M%S', 'now', 'localtime') WHERE user_id = :uid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":sid");
    sqlite3_bind_text(stmt, idx, session_id.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error setting session id. ErrorCode : " << rv << std::endl;

    sqlite3_finalize(stmt);
    return session_id;

}

/**
 * End the session by pushing back the session start time.
 * @param session_id the session_id.
 * @return @b true if successful, @b false otherwise.
 */
bool Database::logout(std::string session_id)
{
    int rv, idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "UPDATE users SET session_start = (strftime('%Y%m%d%H%M%S', 'now', 'localtime') - :sstart) WHERE session_id = :sid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":sstart");
    sqlite3_bind_int(stmt, idx, OPTIONS->session_time_limit);

    idx = sqlite3_bind_parameter_index(stmt, ":sid");
    sqlite3_bind_text(stmt, idx, session_id.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error updating session start time" << std::endl;

    sqlite3_finalize(stmt);

    return true;
}

/**
 * Determines if a user has already submitted a vote.
 * @param user_id the user_id.
 * @return @b true if the vote slot is full, @b false otherwise.
 */
bool Database::already_voted(std::string procedure)
{
    DEBUG(("DEBUG: Checking for duplicate vote...\n"));
    int rv, idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT * FROM choice WHERE user_id = :uid AND proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    rv = sqlite3_step(stmt);

    switch(rv) {
        case SQLITE_DONE:   /* nothing found */
            sqlite3_finalize(stmt);
            return false;
            break;
        case SQLITE_ROW:
            std::string choice = (char*)sqlite3_column_text(stmt, 2);
            sqlite3_finalize(stmt);
            if( choice == "" ) {
                DEBUG(("DEBUG: No Vote\n"));
                return false;
            } else {
                DEBUG(("WARNING: Already Voted"));
                return true;
            }
    }

}

/**
 * Determines if a user has already submitted a public key.
 * @param user_id the user_id.
 * @return @b true if the key slot is full, @b false otherwise.
 */
bool Database::already_submitted_key(std::string procedure)
{
    DEBUG(("DEBUG: Checking for duplicate key...\n"));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT public_key FROM is_authority WHERE user_id = :uid AND proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    rv = sqlite3_step(stmt);

    switch(rv) {
        case SQLITE_DONE:   /* nothing found */
            sqlite3_finalize(stmt);
            return false;
            break;
        case SQLITE_ROW:
            std::string public_key = (char*)sqlite3_column_text(stmt, 0);
            sqlite3_finalize(stmt);
            if( public_key == "" ) {
                DEBUG(("DEBUG: No key\n"));
                return false;
            } else {
                DEBUG(("WARNING: Already  submitted key: $%s$\n", public_key.c_str()));
                return true;
            }
    }

}

/**
 * Determines if an authority has already submitted a partial decryption sum.
 * @return @b true if the authority has already submitted a sum, @b false
 * otherwise.
 */
bool Database::already_submitted_sum(std::string procedure)
{
    DEBUG(("DEBUG: Checking for duplicate sum...\n"));

    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT partial_decryption_sum FROM preresult WHERE user_id = :uid AND proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    rv = sqlite3_step(stmt);

    switch(rv) {
        case SQLITE_DONE:   /* nothing found */
            sqlite3_finalize(stmt);
            return false;
            break;
        case SQLITE_ROW:
            std::string partial_decryption_sum = (char*)sqlite3_column_text(stmt, 0);
            sqlite3_finalize(stmt);
            if( partial_decryption_sum == "" ) {
                DEBUG(("DEBUG: No sum\n"));
                return false;
            } else {
                DEBUG(("WARNING: Already  submitted sum: $%s$\n", partial_decryption_sum.c_str()));
                return true;
            }
    }

}

/**
 * Determines if a procedure exists.
 * @param proc_id the procedure ID.
 * @return @b true if the procedure exists, @b false otherwise.
 */
bool Database::procedure_exists(std::string proc_id)
{
    DEBUG(("Checking if procedure exists...\n"));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT proc_id FROM proc WHERE proc_id = :procid",
            -1, &stmt, NULL);
    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    rv = sqlite3_step(stmt);
    sqlite3_finalize(stmt);

    if(rv == SQLITE_ROW) {
        return true;
    } else {
        return false;
    }
}

/**
 * Retrieves the procedure public key.
 * @return the procedure public key.
 */
adder::PublicKey Database::get_pub_key(std::string procedure)
{
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT public_key FROM proc_pubkey WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    adder::PublicKey pub_key(adder_ctx);

    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        std::string pub_key_str((char*) sqlite3_column_text(stmt, 0));
        try {
            pub_key.from_str(pub_key_str);
        } catch (adder::Invalid_key e) {
            DEBUG(("ERROR: Error getting procedure public key: %s\n", ""));
            return pub_key;
        }
    } else {
        Assert<Errors::Empty> (rv != SQLITE_DONE);
    }

    sqlite3_finalize(stmt);
    return pub_key;
}

/**
 * Returns the number of authorities that are currently present.
 * @return the number of authorities.
 */
int Database::get_authority_count(std::string procedure)
{
    STAGE s = get_stage(procedure);
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT COUNT(*) FROM is_authority WHERE stage = :stg AND proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":stg");

    if( s < STAGE_COMPUTINGPUBKEY) {
        sqlite3_bind_int(stmt, idx, s);
    } else if (s == STAGE_WAITDECRYPT) {
        sqlite3_bind_int(stmt, idx, STAGE_WAITDECRYPT);
    } else {
        sqlite3_bind_int(stmt, idx, STAGE_WAITGETPRIVKEYS);
    }

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    int num_authorities = 0;

    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW )
        num_authorities = sqlite3_column_int(stmt, 0);

    sqlite3_finalize(stmt);
    return num_authorities;

}

int Database::get_remaining_authorities(std::string procedure)
{
    int remaining = (get_threshold(procedure) * get_robustness(procedure))
        - get_authority_count(procedure);

    if (remaining <= 0) {
        return 0;
    } else {
        return remaining;
    }
}

/**
 * Computes the total sum and stores it.
 */
void Database::compute_sum(std::string procedure)
{
    DEBUG(("Computing total sum...\n"));
    int idx, rv;
    adder::PublicKey pub_key(adder_ctx);

    try {
        pub_key = get_pub_key(procedure);
    } catch (...) {
        return;
    }

    adder::Integer modulus = pub_key.get_p();

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT choice FROM choice WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::vector<adder::Vote> votes;
    int num_votes = 0;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        std::string vote_str((char*)sqlite3_column_text(stmt, 0));
        adder::Vote vote;

        try {
            vote.from_str(vote_str);
        } catch(adder::Invalid_vote e) {
            DEBUG(("Error: Error loading vote \n"));
            num_votes = 0;
            return;
        }

        votes.push_back(vote);
        DEBUG(("DEBUG: Adding vote %s...\n", vote.str().c_str()));
        num_votes++;
    }

    adder::Vote sum = adder::sum_votes(votes, modulus);

    sqlite3_finalize(stmt);
    stmt = NULL;

    std::stringstream query;
    query << "INSERT INTO cipher_result VALUES(\"" << procedure
            << "\", \"" << sum.str() << "\", " << num_votes << ")";

    sqlite3_prepare_v2(db, query.str().c_str(), -1, &stmt, NULL);

    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        DEBUG(("ERROR: Sum has already been computed\n"));

    sqlite3_finalize(stmt);
}

/**
 * Aggregates the public keys and stores the result.
 */
void Database::aggregate_keys(std::string procedure)
{
    DEBUG(("Aggregating public keys...\n"));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT value FROM auth_g_values WHERE proc_id = :procid AND number = 0",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    adder::PublicKey master_key = get_master_key(procedure);
    adder::Integer p = master_key.get_p();
    adder::Integer h("1", p, 10);

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        h = h * adder::Integer(std::string((char*)sqlite3_column_text(stmt, 0)), p, 10);
    }

    sqlite3_finalize(stmt);
    adder::PublicKey server_pub_key(adder_ctx, p, master_key.get_g(), h, master_key.get_f());
    std::cout << "Server pub Key : " << server_pub_key.str() << std::endl;
    stmt = NULL;

    std::string query = "INSERT INTO proc_pubkey VALUES(\"" + procedure + "\", \"" + server_pub_key.str() + "\")";

    sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, NULL);

    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        DEBUG(("ERROR: Public key has already been aggregated for procedure %s\n", procedure.c_str()));

    sqlite3_finalize(stmt);

}

/**
 * Decrypts the final sum.
 */
void Database::decrypt_sum(std::string procedure)
{
    int idx;
    adder::PublicKey master_key = get_master_key(procedure);

    adder::Integer p = master_key.get_p();
    adder::Integer f = master_key.get_f();
    adder::Integer g = master_key.get_g();

    adder::Integer q = (p - 1) / 2;

    adder::Polynomial polynomial(adder_ctx,
                                 master_key.get_p(),
                                 master_key.get_g(),
                                 master_key.get_f());

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT preresult.user_id, is_authority.number, preresult.partial_decryption_sum FROM is_authority, preresult WHERE preresult.user_id = is_authority.user_id AND preresult.proc_id = is_authority.proc_id AND preresult.proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::vector<adder::Integer> coeffs;
    std::vector< std::vector<adder::Integer> > partial_sums;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        adder::Integer auth_id(std::string((char*)sqlite3_column_text(stmt, 1)), q, 10);
	//NC20101106 For some reason (?), relaxing a bit the expression allowed it to compile, otherwise we got error: size of array 'row' has non-integral type 'const char [7]'
        std::string partial_decryption = (char*)sqlite3_column_text(stmt, 2);

        coeffs.push_back(auth_id);

        std::vector<std::string> sum_vec = tokenize(partial_decryption);

        std::vector<adder::Integer> auth_vec;
        for (unsigned int j = 0; j < sum_vec.size(); j++) {
            auth_vec.push_back(adder::Integer(sum_vec[j], p, 10));
            DEBUG(("DEBUG: Added to auth_vec: %s\n", auth_vec[j].str().c_str()));
        }

        partial_sums.push_back(auth_vec);
    }

    sqlite3_finalize(stmt);
    
    adder::Vote sum = get_sum(procedure);

    DecryptionHandler* dh = new DecryptionHandler(partial_sums,
                                                  coeffs,
                                                  sum,
                                                  get_num_votes(procedure),
                                                  master_key,
                                                  procedure,
                                                  adder_ctx);

    set_stage(procedure, STAGE_DECRYPTING);
	dh->sevc();
}

void Database::post_results(std::vector<adder::Integer> results)
{
    DEBUG(("Posting results...\n"));
    int idx, rv, choice_id = 0;
    std::vector<adder::Integer>::iterator j;

    sqlite3_stmt *stmt = NULL;
    for (j = results.begin(); j != results.end(); j++, choice_id++) {
        sqlite3_prepare_v2(db,
                "INSERT INTO result VALUES (:procid, :choiceid, :iterj)",
                -1, &stmt, NULL);

        idx = sqlite3_bind_parameter_index(stmt, ":procid");
        sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

        idx = sqlite3_bind_parameter_index(stmt, ":choiceid");
        sqlite3_bind_int(stmt, idx, choice_id);

        idx = sqlite3_bind_parameter_index(stmt, ":iterj");
        sqlite3_bind_int(stmt, idx, atoi(j->str().c_str()));

        std::cout << "inserting result: choiceid-votes -> " << choice_id << "-" << j->str() << std::endl;

        if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
            std::cerr << "Error @ post_results. ErrorCode: " << std::endl;
        sqlite3_finalize(stmt);
        stmt = NULL;
    }

    set_stage(procedure, STAGE_FINISHED);
}

/**
 * Gets the encrypted sum.
 * @return the sum.
 */
adder::Vote Database::get_sum(std::string procedure)
{
    DEBUG(("Getting the encrypted sum...\n"));
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT cipher_sum FROM cipher_result WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::string cipher_sum_str;
    if( sqlite3_step(stmt) == SQLITE_ROW )
        cipher_sum_str = (char*) sqlite3_column_text(stmt, 0);
    else
        DEBUG(("ERROR: Error getting vote sum\n"));

    sqlite3_finalize(stmt);
    adder::Vote cipher_sum;

    try {
        cipher_sum.from_str(cipher_sum_str);
    } catch (adder::Invalid_vote e) {
        DEBUG(("ERROR: Error getting vote sum: %s\n", ""));
        return cipher_sum;
    }

    return cipher_sum;
}

/**
 * Gets the total number of users who have voted.
 * @return the number of users who have voted.
 */
std::string Database::get_num_votes(std::string procedure)
{
    DEBUG(("Getting total number of users that voted...\n"));
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT vote_count FROM cipher_result WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::string num_votes;
    if( sqlite3_step(stmt) == SQLITE_ROW )
        num_votes = (char*)sqlite3_column_text(stmt, 0);
    else
        DEBUG(("ERROR: Couldn't get total number of users that voted\n"));

    sqlite3_finalize(stmt);
std::cout << "Num_votes: " << num_votes << "\n";
    return num_votes;
}

/**
 * Gets the total number of voters.
 * @return the total number of voters.
 */
int Database::get_num_voters()
{
    DEBUG(("Getting number of voters...\n"));

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db, "SELECT COUNT(*) FROM users",  -1, &stmt, NULL);

    int num_voters;
    if( sqlite3_step(stmt) == SQLITE_ROW )
        num_voters = sqlite3_column_int(stmt, 0);
    else
        DEBUG(("ERROR: Could not get total number of voters\n"));

    sqlite3_finalize(stmt);

    return num_voters;
}

/**
 * Gets the total number of choices.
 * @return the total number of choices.
 */
int Database::get_num_choices(std::string proc_id)
{
    DEBUG(("Getting number of choices...\n"));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT COUNT(*) FROM proc_choice WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    int num_choices;
    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        num_choices = sqlite3_column_int(stmt, 0);
    } else {
        Assert<Errors::Critical> (rv == SQLITE_ROW);
    }

    sqlite3_finalize(stmt);
    return num_choices;

}

/**
 * Gets the minimum number of choices.
 * @return the minimum number choices.
 */
int Database::get_min_choices(std::string procedure)
{
    int idx, num_votes;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT minchoices FROM proc WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    if( sqlite3_step(stmt) == SQLITE_ROW ) {
        num_votes = sqlite3_column_int(stmt, 0);
    } else {
        DEBUG(("ERROR: Could not retrieve minimum number of choices\n"));
    }

    sqlite3_finalize(stmt);
    return num_votes;
}

/**
 * Gets the maximum number of choices.
 * @return the maximum number choices.
 */
int Database::get_max_choices(std::string procedure)
{
    int idx, num_votes;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT maxchoices FROM proc WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    if( sqlite3_step(stmt) == SQLITE_ROW ) {
        num_votes = sqlite3_column_int(stmt, 0);
    } else {
        DEBUG(("ERROR: Could not retrieve maximum number of choices\n"));
    }

    sqlite3_finalize(stmt);
    return num_votes;
}


/**
 * Get the list of all active procedures.
 * @return a string containing all of the procedures' IDs and titles.
 */
std::string Database::get_procedure_list()
{
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT proc.proc_id, proc.title, proc_data.stage, proc.threshold, proc.robustness, proc.minchoices, proc.maxchoices FROM proc, proc_data WHERE proc.proc_id = proc_data.proc_id",
            -1, &stmt, NULL);

    std::stringstream proc_str;
    proc_str << "";
    dont_quote_auto = true;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        proc_str << "(\"" << (char*)sqlite3_column_text(stmt, 0) << "\","
                << "\"" << (char*)sqlite3_column_text(stmt, 1) << "\","
                << sqlite3_column_int(stmt, 2) << ","
                << get_remaining_authorities(std::string( (char*)sqlite3_column_text(stmt, 0))) << ","
                << sqlite3_column_int(stmt, 3) << ","
                << sqlite3_column_int(stmt, 4) << ","
                << sqlite3_column_int(stmt, 5) << ","
                << sqlite3_column_int(stmt, 6) << "),";
    }

    dont_quote_auto = false;
    sqlite3_finalize(stmt);

    std::string proc_string(proc_str.str());
    if( proc_string.length() > 2 )
        proc_string.erase(proc_string.length() - 1); // Remove the trailing comma.

    return proc_string;
}

/**
 * Get the list of all active procedures.
 * @return a string containing all of the procedures' IDs and titles.
 */
std::string Database::get_procedure_list2()
{

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT proc.proc_id, proc.title, proc_data.stage FROM proc, proc_data WHERE proc.proc_id = proc_data.proc_id",
            -1, &stmt, NULL);

    std::stringstream proc_str;
    proc_str << "";

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        proc_str << (char*)sqlite3_column_text(stmt, 0)
                << (char*)sqlite3_column_text(stmt, 1)
                << "'" << sqlite3_column_int(stmt, 2) << "'\n";
    }

    sqlite3_finalize(stmt);
    std::string proc_string(proc_str.str());

    return proc_string;
}

/**
 * Get the list of all users.
 * @return a string containing all of the users' IDs.
 */
std::string Database::get_user_list(std::string user_id)
{
	int rv, idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT user_id FROM users WHERE deleted = 0 AND user_id > :uid",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":uid");
	sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    std::stringstream user_str;
    user_str << "(";

    dont_quote_auto = true;
    int it = 0;
    while( (rv = sqlite3_step(stmt)) == SQLITE_ROW )
    {
        it++;
	if (user_str.str().length() + strlen((char*)sqlite3_column_text(stmt, 0) + 20) < 8*10 )
            user_str << "\"" << (char*)sqlite3_column_text(stmt, 0) << "\",";
		else 
		    break;
    }
    dont_quote_auto = false;
    sqlite3_finalize(stmt);

    if( it == 0 ) return "";

    std::string user_string(user_str.str());
    user_string.erase(user_string.length() - 1);

	if( rv != SQLITE_ROW )
		user_string += ",\"_END_\"";
    return user_string + ")\n";
}

/**
 * Get the list of all users.
 * @return a string containing all of the users' IDs.
 */
std::string Database::get_user_list2()
{
    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT user_id FROM users WHERE deleted  = 0",
            -1, &stmt, NULL);

    std::stringstream user_str;

    int it = 0;
    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        it++;
        user_str << (char*)sqlite3_column_text(stmt, 0) << "\n";
    }
    sqlite3_finalize(stmt);

    if( it == 0 ) return "";

    std::string user_string(user_str.str());

    return user_string;

}

/**
 * Get the list of all authorities who have submitted public keys.
 * @return a string containing all of the authorities' user IDs.
 */
std::string Database::get_pubkey_list(std::string procedure)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT user_id FROM is_authority WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::stringstream key_str;
    int it = 0;
    while(sqlite3_step(stmt) == SQLITE_ROW)
    {
        it++;
        key_str << (char*)sqlite3_column_text(stmt, 0) << "\n";
    }

    sqlite3_finalize(stmt);
    if(it == 0) return "";

    std::string key_string(key_str.str());

    return key_string;
}

/**
 * Get the list of all authorities who have submitted public keys.
 * @return a string containing all of the authorities' user IDs.
 */
std::string Database::get_pubkey_list2(std::string procedure)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT user_id FROM is_authority WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::stringstream key_str;
    int it = 0;
    while(sqlite3_step(stmt) == SQLITE_ROW)
    {
        it++;
        key_str << (char*)sqlite3_column_text(stmt, 0) << "\n";
    }

    sqlite3_finalize(stmt);
    if(it == 0) return "";

    std::string key_string(key_str.str());

    return key_string;
}

/**
 * Get the authorities' private keys.
 * @return a list of the private keys.
 */
std::vector<adder::ElgamalCiphertext>
Database::get_priv_key_list(std::string procedure)
{
    Assert<Errors::Baduser> (user != "");
    Assert<Errors::Notauthority> (get_is_authority());
    Assert<Errors::Badauthstage>
        (get_auth_stage(procedure, user) >= STAGE_WAITPOLYNOMIAL);

    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT value FROM auth_poly WHERE proc_id = :procid AND auth_dest = :authdest",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	idx = sqlite3_bind_parameter_index(stmt, ":authdest");
	sqlite3_bind_text(stmt, idx, user.c_str(), -1, SQLITE_STATIC);

    std::vector<adder::ElgamalCiphertext> priv_key_list;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        std::string priv_key_str((char*)sqlite3_column_text(stmt, 0));
        adder::ElgamalCiphertext priv_key;
        priv_key.from_str(priv_key_str);
        priv_key_list.push_back(priv_key);
    }

    sqlite3_finalize(stmt);
    stmt = NULL;

    sqlite3_prepare_v2(db,
            "UPDATE is_authority SET stage = 3 WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);
    
    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error: get_priv_key_list. Errorcode: " << rv << std::endl;

    sqlite3_finalize(stmt);
    return priv_key_list;
}

/**
 * Get the list of all users who have submitted votes.
 * @return a string containing all of the users' IDs.
 */
std::string Database::get_vote_list(std::string procedure, std::string user_id)
{
    DEBUG(("Getting list of users that submitted votes...\n"));
    int idx, i;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT user_id, time_stamp FROM choice WHERE proc_id = :procid AND user_id > :uid ",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);
	
    idx = sqlite3_bind_parameter_index(stmt, ":uid");
	sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    std::vector< std::pair<std::string, std::string> > vote_vec;

    while(sqlite3_step(stmt) == SQLITE_ROW)
    {
        vote_vec.push_back(std::pair<std::string, std::string>
                ("\"" + std::string((char*)sqlite3_column_text(stmt, 0)) + "\"",
                 "\"" + std::string((char*)sqlite3_column_text(stmt, 1)) + "\""));
    }

    sqlite3_finalize(stmt);

	std::stringstream vote_ss;
        
    vote_ss << "\"" << procedure << "\",(";
	
    for (i = 0; i < vote_vec.size(); i++) {
	    if ( (vote_ss.str().length() + vote_vec[i].first.length() + vote_vec[i].second.length() + 30) < 120 )
            vote_ss << "(" << vote_vec[i].first << "," << vote_vec[i].second << "),";
		else
		    break;
    }
    std::string vote_string(vote_ss.str());
    vote_string.erase(vote_string.length() - 1);
	
	std:: cout << "1. Database::get_vote_list:" << vote_string << "\n";
	
	if( i == vote_vec.size())
		vote_string += ",(\"_END_\",\"_END_\")";
        
    vote_string += ')';
	
	std:: cout << "2. Database::get_vote_list:" << vote_string << "\n";
	
    return vote_string;
}

/**
 * Get the list of all users who have submitted votes.
 * @return a string containing all of the users' IDs.
 */
std::string Database::get_vote_list2(std::string procedure)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT user_id, time_stamp FROM choice WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::stringstream vote_str;
    int it = 0;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        it++;
        vote_str << (char*)sqlite3_column_text(stmt, 0) << " "
                << (char*)sqlite3_column_text(stmt, 1) << "\n";
    }

    sqlite3_finalize(stmt);
    if(it == 0) return "\n";

    std::string vote_string(vote_str.str());

    return vote_string;
}

/**
 * Returns the results in the form of a string.
 * @param proc_id the procedure ID.
 * @return a string containing the results.
 */
std::vector< std::pair<std::string, std::string> >
Database::get_results_str(std::string proc_id)
{
    DEBUG(("Getting the results...\n"));
     int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT * FROM result WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    std::stringstream results_str;
    std::vector< std::pair<std::string, std::string> > results_vec;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {

        sqlite3_stmt *stmt2 = NULL;
        sqlite3_prepare_v2(db,
                "SELECT * FROM proc_choice WHERE proc_id = :procid AND choice_id = :cid",
                -1, &stmt2, NULL);

        idx = sqlite3_bind_parameter_index(stmt2, ":procid");
        sqlite3_bind_text(stmt2, idx, proc_id.c_str(), -1, SQLITE_STATIC);

        idx = sqlite3_bind_parameter_index(stmt2, ":cid");
        sqlite3_bind_int(stmt2, idx, sqlite3_column_int(stmt, 1));
        std::cout << sqlite3_column_int(stmt, 1) << std::endl;
        if( (rv = sqlite3_step(stmt2)) != SQLITE_ROW )
            std::cerr << "Error @ get_results_str. ErrorCode: " << rv << std::endl;
        else
            std::cout << sqlite3_column_int(stmt, 1) << " " << sqlite3_column_int(stmt, 2) << " "
                    << sqlite3_column_int(stmt2, 1) << " " << sqlite3_column_text(stmt2, 2) << std::endl;

        int total_votes = sqlite3_column_int(stmt, 2);
        std::stringstream vote_str;
        vote_str << total_votes;

        results_vec.push_back(std::pair<std::string, std::string>
                    ( std::string((char*)sqlite3_column_text(stmt2, 2)),
                    vote_str.str() ));
        sqlite3_finalize(stmt2);
    }

    sqlite3_finalize(stmt);
    return results_vec;
}

/**
 * Returns the results in the form of a string.
 * @param proc_id the procedure ID.
 * @return a string containing the results.
 */
std::string Database::get_results_str2(std::string proc_id)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT * FROM result WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    int it = 0;
    std::stringstream results_str;
    
    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        it++;
        sqlite3_stmt *stmt2 = NULL;
        sqlite3_prepare_v2(db,
                "SELECT * FROM proc_choice WHERE proc_id = :procid AND choice_id = :cid",
                -1, &stmt, NULL);
        
        idx = sqlite3_bind_parameter_index(stmt, ":procid");
        sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

        idx = sqlite3_bind_parameter_index(stmt, ":cid");
        sqlite3_bind_text(stmt, idx, (char*)sqlite3_column_text(stmt, 1), -1, SQLITE_STATIC);
        
        sqlite3_step(stmt);
        results_str << (char*)sqlite3_column_text(stmt2, 2) << " "
                << (char*) sqlite3_column_text(stmt, 2) << "\n";
        
        sqlite3_finalize(stmt2);
    }

    sqlite3_finalize(stmt);

    std::string results_string(results_str.str());

    return results_string;
}

/**
 * Returns the description of a procedure.
 * @param proc_id the procedure.
 * @return a string containing the description.
 */
std::string Database::get_description(std::string proc_id)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
                "SELECT text FROM proc WHERE proc_id = :procid",
                -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    if( sqlite3_step(stmt) != SQLITE_ROW ) {
            sqlite3_finalize(stmt);
            return "";
    }

    std::string description_string((char*)sqlite3_column_text(stmt, 0));
    sqlite3_finalize(stmt);

    return description_string;
}

/**
 * Returns the title of a procedure.
 * @param proc_id the procedure.
 * @return a string containing the title.
 */
std::string Database::get_procedure_title(std::string proc_id)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT title FROM proc WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    if( sqlite3_step(stmt) != SQLITE_ROW ) {
        sqlite3_finalize(stmt);
        return "";
    }

    std::string title_string((char*)sqlite3_column_text(stmt, 0));
    sqlite3_finalize(stmt);

    return title_string;
}

/**
 * Returns a string containing the description of the election choices.
 * @return a string containing the description of the election choices.
 */
std::vector<std::string> Database::get_choices(std::string proc_id)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
                "SELECT * FROM proc_choice WHERE proc_id = :procid",
                -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    std::vector<std::string> choices_vec;

    dont_quote_auto = true;
    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        std::stringstream text_str;
        text_str << (char*)sqlite3_column_text(stmt, 2);
        std::string text = text_str.str();
        choices_vec.push_back(text);
    }
    sqlite3_finalize(stmt);
    dont_quote_auto = false;

    return choices_vec;
}

/**
 * Returns a string containing the description of the election choices.
 * @return a string containing the description of the election choices.
 */
std::vector<std::string> Database::get_choices2(std::string proc_id)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT * FROM proc_choice WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc_id.c_str(), -1, SQLITE_STATIC);

    std::vector<std::string> choices_vec;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        std::string text;
        text = (char*)sqlite3_column_text(stmt, 2);
        text = text.substr(1, text.length() - 2);
        std::stringstream choice_str;
        choice_str << sqlite3_column_int(stmt, 1) << "~" << text;
        choices_vec.push_back(choice_str.str());
    }

    sqlite3_finalize(stmt);
    return choices_vec;
}

/**
 * Gets the public key of an authority.
 * @param auth_id the user id of the authority.
 * @return the public key of the authority.
 */
adder::PublicKey Database::get_auth_pub_key(std::string procedure, std::string auth_id)
{
    DEBUG(("DEBUG: Getting public key of an authority...\n"));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT public_key FROM is_authority WHERE proc_id = :procid AND user_id = :uid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, auth_id.c_str(), -1, SQLITE_STATIC);

    std::string pub_key_str;
    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        pub_key_str = (char*)sqlite3_column_text(stmt, 0);
    } else {
        Assert<Errors::Empty> (rv == SQLITE_ROW);
    }

    sqlite3_finalize(stmt);
    adder::PublicKey pub_key(adder_ctx);

    try {
        pub_key.from_str(pub_key_str);
    } catch (adder::Invalid_key e) {
        DEBUG(("ERROR: Error getting key: %s\n", ""));
        throw Errors::Empty();
    }

    return pub_key;
}

/**
 * Gets the stage of an authority.
 * @param auth_id the user id of the authority.
 * @return the stage of the authority.
 */
int Database::get_auth_stage(std::string procedure, std::string auth_id)
{
    DEBUG(("Getting authority's stage...\n"));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT stage FROM is_authority WHERE proc_id = :procid AND user_id = :uid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, auth_id.c_str(), -1, SQLITE_STATIC);

    int stage;
    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        stage = sqlite3_column_int(stmt, 0);
    } else {
        Assert<Errors::Empty> (rv == SQLITE_ROW);
    }

    sqlite3_finalize(stmt);
    return stage;

}

/**
 * Get the authorities' public keys.
 * @return a list of the public keys.
 */
std::string Database::get_auth_pub_keys(std::string procedure, int num)
{
    DEBUG(("DEBUG: Getting authorities' public keys...\n"));
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT number, public_key FROM is_authority WHERE proc_id = :procid AND number > :num",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);
    
    idx = sqlite3_bind_parameter_index(stmt, ":num");
    sqlite3_bind_int(stmt, idx, num);

    std::vector< std::pair<int, adder::PublicKey> > pub_keys;

    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        std::string key_string = (char*)sqlite3_column_text(stmt, 1);
        int id = sqlite3_column_int(stmt, 0);
        
        if( !key_string.empty() ) {
            try {
                adder::Context context(true);
                adder::PublicKey key(&context);
                key.from_str(key_string);
                std::pair< int, adder::PublicKey > p(id, key);
                pub_keys.push_back(p);
            } catch (...) {
                throw Errors::Critical();
            }
        }
    }
    sqlite3_finalize(stmt);
        
    std::stringstream key_str;
	key_str << "\"" << procedure << "\",(";
        
    std::vector< std::pair<int, adder::PublicKey> >::iterator i; int j;
    for (j=0, i = pub_keys.begin(); i != pub_keys.end(); i++, j++) {
	    if ( key_str.str().length() + i->second.str().length() + 40 < 2000 )
            key_str << "(" << i->first << "," << i->second.str() << "),";
		else
		    break;
    }
    
    std::string key_string(key_str.str());
    key_string.erase(key_string.length() - 1);

	if (j==pub_keys.size()) 
	    key_string += ",(-1,END)";
         
    key_string += ')';
	
	std:: cout << "getauthpubkeys: " << key_string << "\n";
	
    return key_string;
}

/**
 * Get the authorities' public keys.
 * @return a list of the public keys.
 */
std::vector<std::string> Database::get_auth_pub_keys2(std::string procedure)
{
    int idx;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT number, public_key FROM is_authority WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    std::vector<std::string> pub_keys;
    while( sqlite3_step(stmt) == SQLITE_ROW )
    {
        std::string key_string = (char*)sqlite3_column_text(stmt, 1);
        std::stringstream id_str;
        id_str << sqlite3_column_int(stmt, 0);

        if( !key_string.empty() ) {
            pub_keys.push_back(id_str.str() + " " + key_string);
        }
    }

    sqlite3_finalize(stmt);
    return pub_keys;
}

/**
 * Gets the encrypted vote of a user.
 * @param user_id the user id of the user.
 * @return the encrypted vote of the user.
 */
adder::Vote Database::get_vote(std::string procedure, std::string user_id)
{
    DEBUG(("Getting the encrypted vote of user...%s\n", user_id.c_str()));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT choice FROM choice WHERE proc_id = :procid AND user_id = :uid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_ROW )
        Assert<Errors::Empty> (rv == SQLITE_ROW);

    std::string vote_str = (char*)sqlite3_column_text(stmt, 0);
    adder::Vote vote;

    sqlite3_finalize(stmt);

    try {
        vote.from_str(vote_str);
    } catch (adder::Invalid_key e) {
        DEBUG(("ERROR: Error loading vote: %s\n", ""));
        throw Errors::Empty();
    }

    return vote;
}

/**
 * Gets the ballot proof of a user.
 * @param user_id the user id of the user.
 * @return the ballot proof of the user.
 */
adder::VoteProof
Database::get_ballot_proof(std::string procedure, std::string user_id)
{
    DEBUG(("Getting the ballot proof of user... %s\n", user_id.c_str()));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT proof FROM choice WHERE proc_id = :procid AND user_id = :uid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    std::string proof_str;
    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        proof_str = (char*)sqlite3_column_text(stmt, 0);
    } else {
        Assert<Errors::Empty> (rv == SQLITE_ROW);
    }

    sqlite3_finalize(stmt);

    adder::VoteProof proof;

    try {
        proof.from_str(proof_str);
    } catch (adder::Invalid_key e) {
        DEBUG(("ERROR: Error loading proof: %s\n", ""));
        throw Errors::Empty();
    }

    return proof;
}

/**
 * Gets the short hash of a user.
 * @param user_id the user id of the user.
 * @return the short hash of the user.
 */
std::string Database::get_short_hash(std::string procedure, std::string user_id)
{
    DEBUG(("Getting the short hash of user... %s\n", user_id.c_str()));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT short_hash FROM choice WHERE proc_id = :procid AND user_id = :uid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user_id.c_str(), -1, SQLITE_STATIC);

    std::string hash_str;
    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        hash_str = (char*)sqlite3_column_text(stmt, 0);
    } else {
        Assert<Errors::Empty> (rv == SQLITE_ROW);
    }

    sqlite3_finalize(stmt);
    return hash_str;
}

/**
 * Adds a vote for the user.
 * @param vote the vote to be added.
 */
void Database::add_vote(std::string procedure, adder::Vote vote,
                        adder::VoteProof proof)
{
    DEBUG(("Adding vote...\n"));
    Assert<Errors::Duplicate> (!already_voted(procedure));

    sqlite3_stmt *stmt = NULL;
    std::string query = "INSERT INTO choice VALUES(\"" + procedure + "\", \"" + user + "\", \"" +
            vote.str() + "\", \"SHORT HASH\", \"" + proof.str() + "\", datetime('now', 'localtime'))";

    sqlite3_prepare_v2(db, query.c_str(), -1, &stmt, NULL);

    if( sqlite3_step(stmt) != SQLITE_DONE )
        std::cerr << "Could not add vote" << std::endl;

    sqlite3_finalize(stmt);
}

/**
 * Insert an authority's polynomial into the database.
 * @param auth_id the "destination" authority's ID.
 * @param poly the polynomial.
 */
void Database::add_poly(std::string procedure,
                        std::vector< std::pair<std::string, std::string> >
                        &poly_vec)
{
    DEBUG(("Inserting an authority's polynomial in database...(add_poly).\n"));

    Assert<Errors::Badauthstage> (get_auth_stage(procedure, user) == STAGE_WAITKEYS);
    for (int j = 0; j < poly_vec.size(); j++) {
        int idx, rv;
        sqlite3_stmt *stmt = NULL;
        sqlite3_prepare_v2(db,
                "SELECT user_id FROM is_authority WHERE proc_id = :procid AND number = :numb",
                -1, &stmt, NULL);

        idx = sqlite3_bind_parameter_index(stmt, ":procid");
        sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

        idx = sqlite3_bind_parameter_index(stmt, ":numb");
        sqlite3_bind_text(stmt, idx, poly_vec[j].first.c_str(), -1, SQLITE_STATIC);

        std::string auth_name;
        if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
            auth_name = (char*)sqlite3_column_text(stmt, 0);
        } else {
            Assert<Errors::Empty> (rv == SQLITE_ROW);
        }

        sqlite3_finalize(stmt);

        try {
            int idx, rv;
            sqlite3_stmt *stmt2 = NULL;
            sqlite3_prepare_v2(db,
                    "INSERT INTO auth_poly VALUES(:procid, :uid, :auth, :pvec)",
                    -1, &stmt2, NULL);

            idx = sqlite3_bind_parameter_index(stmt2, ":procid");
            sqlite3_bind_text(stmt2, idx, procedure.c_str(), -1, SQLITE_STATIC);

            idx = sqlite3_bind_parameter_index(stmt2, ":uid");
            sqlite3_bind_text(stmt2, idx, user.c_str(), -1, SQLITE_STATIC);

            idx = sqlite3_bind_parameter_index(stmt2, ":auth");
            sqlite3_bind_text(stmt2, idx, auth_name.c_str(), -1, SQLITE_STATIC);

            idx = sqlite3_bind_parameter_index(stmt2, ":pvec");
            sqlite3_bind_text(stmt2, idx, poly_vec[j].second.c_str(), -1, SQLITE_STATIC);

            if( (rv = sqlite3_step(stmt2)) != SQLITE_DONE ) {
                std::cerr << "Error. Function: add_poly(insert). ErrorCode: " << rv << std::endl;
            }
            sqlite3_finalize(stmt2);
            stmt2 = NULL;

            sqlite3_prepare_v2(db,
                    "UPDATE is_authority SET stage = 2 WHERE proc_id = :procid AND user_id = :uid",
                    -1, &stmt2, NULL);

            idx = sqlite3_bind_parameter_index(stmt2, ":procid");
            sqlite3_bind_text(stmt2, idx, procedure.c_str(), -1, SQLITE_STATIC);

            idx = sqlite3_bind_parameter_index(stmt2, ":uid");
            sqlite3_bind_text(stmt2, idx, user.c_str(), -1, SQLITE_STATIC);

            if( (rv = sqlite3_step(stmt2)) != SQLITE_DONE ) {
                std::cerr << "Error. Function: add_poly(update). ErrorCode: " << rv << std::endl;
            }
            sqlite3_finalize(stmt2);

        } catch(...) {
            throw Errors::Critical();
        }
    }

}

/**
 * Insert an authority's g-value into the database.
 * @param number the number.
 * @param value the value of g.
 */
void Database::add_gvalue(std::string procedure,
                          std::vector< std::pair<int, std::string> > &gvalue_vec)
{
    DEBUG(("Adding authority's g-value in database...\n"));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "INSERT INTO auth_g_values VALUES(:procid, :uid, :gval1, :gval2)",
            -1, &stmt, NULL);

    for( int i = 0; i < gvalue_vec.size(); i++ ) {

        idx = sqlite3_bind_parameter_index(stmt, ":procid");
         sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

        idx = sqlite3_bind_parameter_index(stmt, ":uid");
        sqlite3_bind_text(stmt, idx, user.c_str(), -1, SQLITE_STATIC);

        idx = sqlite3_bind_parameter_index(stmt, ":gval1");
        sqlite3_bind_int(stmt, idx, gvalue_vec[i].first);

        idx = sqlite3_bind_parameter_index(stmt, ":gval2");
        sqlite3_bind_text(stmt, idx, gvalue_vec[i].second.c_str(), -1, SQLITE_STATIC);

        if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
            std::cerr << "Error @ add_gvalue. ErrorCode: " << rv << std::endl;

        sqlite3_reset(stmt);
    }

    sqlite3_finalize(stmt);
}

/**
 * Adds a key for the user.
 * @param key the key to be added.
 */
void Database::add_key(std::string procedure, adder::PublicKey key)
{
    DEBUG(("DEBUG: Adding a key for a user...\n"));
    Assert<Errors::Duplicate> (!already_submitted_key(procedure));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;

    std::stringstream ss;
    ss << "UPDATE is_authority SET public_key = \"" << key.str() << "\" , stage = 1 WHERE proc_id = \""
            << procedure << "\" AND user_id = \"" << user << "\"";

    sqlite3_prepare_v2(db, ss.str().c_str(), -1, &stmt, NULL);
    
    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error @ add_key. ErrorCode: " << rv << std::endl;

    sqlite3_finalize(stmt);

}

/**
 * Adds a partially-decrypted sum for the user.
 * @param sum the sum partial decryption to be added.
 */
void Database::add_sum(std::string procedure, std::vector<adder::Integer> sum_vec)
{
    DEBUG(("Adding a partially-decrypted sum for the user...\n"));
    Assert<Errors::Badauthstage>
        (get_auth_stage(procedure, user) == STAGE_WAITGETPRIVKEYS);

    Assert<Errors::Duplicate> (!already_submitted_sum(procedure));

    int idx, rv;
    std::string sum_str;
    for( unsigned int i = 0; i < sum_vec.size(); i++ ) {
        sum_str += sum_vec[i].str() + ' ';
    }

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "INSERT INTO preresult VALUES(:procid, :uid, :sum)",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":sum");
    sqlite3_bind_text(stmt, idx, sum_str.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error @ add_sum. ErrorCode: " << rv << std::endl;

    sqlite3_finalize(stmt);
    stmt = NULL;


    sqlite3_prepare_v2(db,
            "UPDATE is_authority SET stage = 7 WHERE proc_id = :procid AND user_id = :uid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, user.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error @ add_sum. ErrorCode: " << rv << std::endl;

    sqlite3_finalize(stmt);
}

/**
 * Sets the Adder Context.
 * @param ctx a pointer to the Adder context.
 */
void Database::set_context(adder::Context* ctx)
{
    adder_ctx = ctx;
}

/**
 * Set the procedure to which future requests over this connection will refer.
 * @param proc the procedure ID.
 * @return @b true if the procedure exists, @b false otherwise.
 */
bool Database::set_procedure(std::string proc)
{
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "SELECT proc_id FROM proc WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, proc.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_ROW ) {
        std::cerr << "Error @ set_procedure. ErrorCode: " << rv << std::endl;
        return false;
    }

    sqlite3_finalize(stmt);
    procedure = proc;
    return true;
}

/**
 * Update the stage of the server for this procedure.
 * @param new_stage the stage to which the server should switch.
 * @param procedure the procedure.
 */
void Database::set_stage(std::string procedure, STAGE new_stage)
{
    DEBUG(("Setting stage... %d\n", new_stage));
    int idx, rv;

    sqlite3_stmt *stmt = NULL;
    sqlite3_prepare_v2(db,
            "UPDATE proc_data SET stage = :stg WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":stg");
    sqlite3_bind_int(stmt, idx, new_stage);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error @ set_stage. ErrorCode: " << rv << std::endl;

    sqlite3_finalize(stmt);
}

//////////jp
/**
 * Sets the user ID.
 * @param user_id the user_id.
 */
void Database::set_user(std::string user_id)
{
    user = user_id;
}

/**
 * Gets the user ID.
 * @return the user_id.
 */
std::string Database::get_user()
{
    return user;
}

/**
 * Gets the authority's number.
 * @return the authority's number.
 */
int Database::get_auth_num(std::string procedure, std::string id)
{
    DEBUG(("DEBUG: Getting authority's number...\n"));

    int idx, rv;
    sqlite3_stmt *stmt = NULL;

    sqlite3_prepare_v2(db,
            "SELECT number FROM is_authority WHERE user_id = :uid AND proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":uid");
    sqlite3_bind_text(stmt, idx, id.c_str(), -1, SQLITE_STATIC);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) != SQLITE_ROW ) {
        return false;
    }

    int auth_num = sqlite3_column_int(stmt, 0);
    sqlite3_finalize(stmt);
    return auth_num;
}


int Database::get_auth_num(std::string procedure)
{
    return get_auth_num(procedure, user);
}

/**
 * Gets the authority status of the user.
 * @return @t true if the user is an authority, @b false otherwise.
 */
bool Database::get_is_authority()
{
    return is_authority;
}

/**
 * Generate the master key for this procedure.
 */
void Database::gen_master_key(std::string procedure, int length)
{
    DEBUG(("Generating procedure's master key..\n"));

    int idx, rv; std::string empty = "";
    sqlite3_stmt *stmt = NULL;
    adder::PublicKey master_key(adder_ctx);

    // XXX: why not stick this in a constant?
    master_key.make_partial_key(adder::Integer("125489087238195737954347303072014181609743210685664342148563282627702888711600616104630041189823615830151059574742027596462279644487544647092987402728428983866463990803061712929699319731954518354611104476983414003271056663266811843871036977620134268053541312343523587317149772597056898709288705318111363439959", 10));
    //    master_key.make_partial_key(adder::Integer("51203"));

    char query[2000];
    sprintf(query, "INSERT INTO proc_masterkey VALUES('%s', '%s', '%s')", procedure.c_str(), master_key.str().c_str(), "");
    sqlite3_prepare_v2(db, query, -1, &stmt, NULL);
 
     if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
         std::cout << "Error @ gen_master_key. ErrorCode: " << rv << std::endl;
     sqlite3_finalize(stmt);

}


/**
 * Get the stage of the server for this procedure.
 * @param procedure the procedure.
 * @return the stage.
 */
STAGE Database::get_stage(std::string procedure)
{
    DEBUG(("DEBUG: Getting stage...\n"));

    int idx, rv;
    sqlite3_stmt *stmt = NULL;
    int stage;

    sqlite3_prepare_v2(db, 
            "SELECT stage FROM proc_data WHERE proc_id =  :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW ) {
        stage = sqlite3_column_int(stmt, 0);
        sqlite3_finalize(stmt);
        return (STAGE)stage;
    }
    else
        sqlite3_finalize(stmt);
    return STAGE_NONEXIST;  // FIXME: throw exception here?
}

/**
 * Get the ID of the procedure that is currently selected.
 * @return the procedure ID.
 */
std::string Database::get_procedure()
{
    return procedure;
}

/**
 * Get the authority threshold for the selected procedure.
 * @return the threshold.
 */
int Database::get_threshold(std::string procedure)
{
    int idx;
    sqlite3_stmt *stmt = NULL;
    std::string threshold_str;

    sqlite3_prepare_v2(db, "SELECT threshold FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    sqlite3_step(stmt);
    threshold_str = (char*)sqlite3_column_text(stmt, 0);
    sqlite3_finalize(stmt);
    int threshold = atoi(threshold_str.c_str());
    return threshold;
}

/**
 * Get the procedure creation time.
 *
 * @return the procedure creation time (in unix time)
 */
int Database::get_create_time(std::string procedure)
{
    DEBUG(("Getting procedure's creation time...\n"));
    int idx;
    sqlite3_stmt *stmt = NULL;
    std::string create_time_str;

    sqlite3_prepare_v2(db, "SELECT create_time FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    sqlite3_step(stmt);
    create_time_str = (char*)sqlite3_column_text(stmt, 0);
    sqlite3_finalize(stmt);
    int create_time = atoi(create_time_str.c_str());
    return create_time;
}
/**
 * Get the time allowed for voting.
 * @return the number of seconds voting will last.
 */
int Database::get_vote_time(std::string procedure)
{
    int idx;
    sqlite3_stmt *stmt = NULL;
    std::string vote_time_str;

    sqlite3_prepare_v2(db, "SELECT vote_time FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    sqlite3_step(stmt);
    vote_time_str = (char*)sqlite3_column_text(stmt, 0);
    sqlite3_finalize(stmt);
    int vote_time = atoi(vote_time_str.c_str());
    return vote_time;
}
/**
 * Get the time allowed for submitting polynomials.
 * @return the number of seconds polynomial submission will last.
 */
int Database::get_public_key_time(std::string procedure)
{
    int idx;
    sqlite3_stmt *stmt = NULL;
    std::string public_key_time_str;

    sqlite3_prepare_v2(db, "SELECT public_key_time FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    sqlite3_step(stmt);

    public_key_time_str = (char*)sqlite3_column_text(stmt, 0);
    sqlite3_finalize(stmt);
    int public_key_time = atoi(public_key_time_str.c_str());
    return public_key_time;
}


/**
 * Get the time allowed for submitting polynomials.
 * @return the number of seconds polynomial submission will last.
 */
int Database::get_polynomial_time(std::string procedure)
{
    int idx;
    sqlite3_stmt *stmt = NULL;
    std::string polynomial_time_str;

    sqlite3_prepare_v2(db, "SELECT polynomial_time FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    sqlite3_step(stmt);
    polynomial_time_str = (char*)sqlite3_column_text(stmt, 0);
    sqlite3_finalize(stmt);
    int polynomial_time = atoi(polynomial_time_str.c_str());
    return polynomial_time;

}


/**
 * Get the time allowed for submitting secret keys.
 * @return the number of seconds secret key submission will last.
 */
int Database::get_secret_key_time(std::string procedure)
{

    int idx;
    sqlite3_stmt *stmt = NULL;
    std::string secret_key_time_str;

    sqlite3_prepare_v2(db, "SELECT secret_key_time FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    sqlite3_step(stmt);
    secret_key_time_str = (char*)sqlite3_column_text(stmt, 0);
    sqlite3_finalize(stmt);
    int secret_key_time = atoi(secret_key_time_str.c_str());
    return secret_key_time;

}

/**
 * Get the robustness factor.
 * @return the robustness factor.
 */
int Database::get_robustness(std::string procedure)
{
    int idx;
    sqlite3_stmt *stmt = NULL;
    std::string robustness_str;

    sqlite3_prepare_v2(db, "SELECT robustness FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    sqlite3_step(stmt);
    robustness_str = (char*)sqlite3_column_text(stmt, 0);
    sqlite3_finalize(stmt);
    int robustness = atoi(robustness_str.c_str());
    return robustness;

}

/**
 * Creates a new procedure.
 * @param id the procedure ID.
 * @param proc_info the procedure information.
 * @return true if successful, false otherwise.
 */
bool Database::create_procedure(std::string id, std::string title,
                                std::string text, int threshold,
                                int publickeytime, int polynomialtime, int secretkeytime,
                                int votetime, int keylength, int robustness,
                                int minchoices, int maxchoices,
                                std::vector<std::string> choices_vec,
                                std::vector<std::string> auths)
{
    DEBUG(("DEBUG: Creating procedure %s...\n", id.c_str()));

    int rv, idx;
    sqlite3_stmt *stmt = NULL;

    procedure = id;

    /* Ensure that the min choices and max choices fall in the
       appropriate range. */
    if (minchoices > maxchoices or maxchoices > choices_vec.size()) {
        DEBUG(("ERROR: Choices out of range\n"));
        return false;
    }

    std::vector<std::string>::iterator i;
    int j = 1;
    try {
    	sqlite3_prepare_v2(db, "INSERT INTO is_authority VALUES(:i, :id, :j, \"\", 0)", -1, &stmt, NULL);

    	for (i = auths.begin(); i != auths.end(); i++, j++) {

    	    idx = sqlite3_bind_parameter_index(stmt, ":i");
            sqlite3_bind_text(stmt, idx, (*i).c_str(), -1, SQLITE_STATIC);

            idx = sqlite3_bind_parameter_index(stmt, ":id");
            sqlite3_bind_text(stmt, idx, id.c_str(), -1, SQLITE_STATIC);

            idx = sqlite3_bind_parameter_index(stmt, ":j");
            sqlite3_bind_int(stmt, idx, j);

            rv = sqlite3_step( stmt );
            if ( rv != SQLITE_DONE ) {
	          return false;
            }

            sqlite3_reset(stmt);
        }

        sqlite3_finalize(stmt);

    }catch(...) {
    	    DEBUG(("DEBUG: Error inserting into is_authority\n"));
            throw Errors:: Critical();
    }

    stmt = NULL;

    char buf[250];

    sprintf(buf,
    	    "INSERT INTO proc VALUES('%s', '%s', '%s', %d, %d, %d, %d, %d, %d, datetime('now', 'localtime'), strftime('%%Y%%m%%d%%H%%M%%S', 'now', 'localtime') * 2, 1024, %d, %d, %d)",
    	    id.c_str(), title.c_str(), text.c_str(), threshold, int(time(0)), publickeytime, polynomialtime, secretkeytime, votetime,
            robustness, minchoices, maxchoices);

    try {
        sqlite3_prepare_v2(db, buf, -1, &stmt, NULL);

        rv = sqlite3_step( stmt );
        if ( rv != SQLITE_DONE ) {
	    return false;
        }

        sqlite3_finalize(stmt);  stmt = NULL;

        sqlite3_prepare_v2(db, "INSERT INTO proc_data VALUES(:id, 0)", -1, &stmt, NULL);

        idx = sqlite3_bind_parameter_index(stmt, ":id");
        sqlite3_bind_text(stmt, idx, id.c_str(), -1, SQLITE_STATIC);

        rv = sqlite3_step( stmt );
        if ( rv != SQLITE_DONE ) {
            DEBUG(("DEBUG: Could not insert into proc_data\n"));
	    return false;
        }

        sqlite3_finalize(stmt);
    }catch (...) {
    	    DEBUG(("DEBUG: Error inserting into proc\n\n"));
    	    throw Errors:: Critical();
    }

    stmt = NULL;

    /* Generate master key info. */
    sqlite3_prepare_v2(db, "SELECT master_key_length FROM proc WHERE proc_id = :procid", -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, id.c_str(), -1, SQLITE_STATIC);

    if( (rv=sqlite3_step(stmt)) != SQLITE_ROW ) {
        DEBUG(("ERROR: Could not retrieve minimum number of choices\n"));
        return false;
    }

    std::string key_length_str = (char*)sqlite3_column_text(stmt, 0);
    int key_length = atoi(key_length_str.c_str());
    gen_master_key(procedure, key_length);

    sqlite3_finalize(stmt); stmt = NULL;

     /* Add choices. */
    adder::PublicKey master_key = get_master_key(procedure);
    adder::Integer p = master_key.get_p();
    std::vector<std::string>::iterator m;
    int num = 0;

    try {
    	    sqlite3_prepare_v2(db, "INSERT INTO proc_choice VALUES(:id, :n, :m)", -1, &stmt, NULL);


    	    for (m = choices_vec.begin(); m != choices_vec.end(); m++, num++) {

    	        idx = sqlite3_bind_parameter_index(stmt, ":id");
                sqlite3_bind_text(stmt, idx, id.c_str(), -1, SQLITE_STATIC);

                idx = sqlite3_bind_parameter_index(stmt, ":n");
                sqlite3_bind_int(stmt, idx, num);

                idx = sqlite3_bind_parameter_index(stmt, ":m");
                sqlite3_bind_text(stmt, idx, (*m).c_str(), -1, SQLITE_STATIC);

                rv = sqlite3_step( stmt );
                if ( rv != SQLITE_DONE ) {
                  DEBUG(("ERROR: Could not add choice: %s\n", (*m).c_str()));
	          return false;
                }

                sqlite3_reset(stmt);
           }

           sqlite3_finalize(stmt);
    }catch (...) {
    	   throw Errors::Critical();
    }

    DEBUG(("DEBUG: Successfully created procedure %s\n", id.c_str()));
    return true;
}

/**
 * Get the master key for this procedure.
 * @return the master key.
 */
adder::PublicKey Database::get_master_key(std::string procedure)
{
    DEBUG(("Getting procedure's master key...\n"));
    int rv, idx;
    sqlite3_stmt *stmt = NULL;
    std::string master_key_str;

    sqlite3_prepare_v2(db,
            "SELECT master_key FROM proc_masterkey WHERE proc_id = :procid",
            -1, &stmt, NULL);

    idx = sqlite3_bind_parameter_index(stmt, ":procid");
    sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

    adder::PublicKey master_key(adder_ctx);

    if( (rv = sqlite3_step(stmt)) == SQLITE_ROW )
        master_key_str = (char*)sqlite3_column_text(stmt, 0);
    else
    	std::cerr << "Error master key" << std::endl;

    try {
        std::cout << "Master key : " << master_key_str << std::endl;
        master_key.from_str(master_key_str);
    } catch (adder::Invalid_key e) {
        throw Errors::Empty();
    }

    sqlite3_finalize(stmt);

    return master_key;

}

void Database::expire_public_key_timer(std::string procedure)
{
    if (get_stage(procedure) != STAGE_WAITKEYS) {
        return;
    }
/*
    if (get_create_time(procedure) + get_polynomial_time(procedure) <= time(0)) {
        set_stage(procedure, STAGE_HALT);
        return;
    }
*/
    if (get_authority_count(procedure) >= get_threshold(procedure) * get_robustness(procedure)) {
    /*    PolynomialTimerHandler* timer = new PolynomialTimerHandler(get_procedure());
        int timeout = get_polynomial_time(procedure);
        ACE_Time_Value initial_delay(timeout);
        ACE_Reactor::instance()->schedule_timer(timer, 0, initial_delay);*/
        set_stage(procedure, STAGE_WAITPOLYNOMIAL);
    } else {
        set_stage(procedure, STAGE_HALT);
    }
}

void Database::expire_polynomial_timer(std::string procedure)
{
    if (get_stage(procedure) != STAGE_WAITPOLYNOMIAL) {
        return;
    }
/*
    if (get_create_time(procedure) + get_secret_key_time(procedure) <= time(0)) {
        set_stage(procedure, STAGE_HALT);
        return;
    }
*/
    if (get_authority_count(procedure) >= get_threshold(procedure) * get_robustness(procedure)) {
    /*    SecretKeyTimerHandler* timer = new SecretKeyTimerHandler(get_procedure());
        int timeout = get_secret_key_time(procedure);
        ACE_Time_Value initial_delay(timeout);
        ACE_Reactor::instance()->schedule_timer(timer, 0, initial_delay);*/
        set_stage(procedure, STAGE_WAITGETPRIVKEYS);
    } else {
        set_stage(procedure, STAGE_HALT);
    }
}

void Database::expire_secret_key_timer(std::string procedure)
{
    if (get_stage(procedure) != STAGE_WAITGETPRIVKEYS) {
        return;
    }
/*
    if (get_create_time(procedure) + get_vote_time(procedure) <= time(0)) {
        set_stage(procedure, STAGE_HALT);
        return;
    }
*/
    if (get_authority_count(procedure) >= get_threshold(procedure) * get_robustness(procedure)) {
        set_stage(procedure, STAGE_COMPUTINGPUBKEY);
        aggregate_keys(procedure);

    /*    ElectionTimerHandler* timer = new ElectionTimerHandler(get_procedure());
        int timeout = get_vote_time(procedure);
        ACE_Time_Value initial_delay(timeout);
        ACE_Reactor::instance()->schedule_timer(timer, 0, initial_delay);*/
        set_stage(procedure, STAGE_VOTING);

    } else {
        set_stage(procedure, STAGE_HALT);
    }
}

void Database::expire_election_timer(std::string procedure)
{
    if (get_stage(procedure) != STAGE_VOTING) {
        return;
    }

    set_stage(procedure, STAGE_ADDCIPHER);
    compute_sum(procedure);
    set_stage(procedure, STAGE_WAITDECRYPT);
}


void Database::make_user(std::string username, std::string password,
                         std::string first_name, std::string middle_name,
                         std::string last_name, std::string email)
{

    int rv, idx, rc;

	sqlite3_stmt *stmt = NULL;
	sqlite3_prepare_v2(db,
            "SELECT * FROM users WHERE user_id = :userid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":userid");
	sqlite3_bind_text(stmt, idx, username.c_str(), -1, SQLITE_STATIC);

	rv = sqlite3_step(stmt);
	sqlite3_finalize(stmt);
	stmt = NULL;

	switch(rv) {
        case SQLITE_ROW:   // User exists already.
            throw Errors::Duplicate();
            break;
        case SQLITE_DONE:
		    std::string salt("0");
			rc = sqlite3_prepare_v2(db,
                    "INSERT INTO users VALUES(:uid, :pass, :fn, :mn, :ln, :mail, :s, 0, NULL, NULL) ",
                    -1, &stmt, NULL);
			if ( rc != SQLITE_OK) {
			    std::cerr << "Error" << std::endl; exit ( -1 );
            }

			idx = sqlite3_bind_parameter_index(stmt, ":uid");
	        sqlite3_bind_text(stmt, idx, username.c_str(), -1, SQLITE_STATIC);

			idx = sqlite3_bind_parameter_index(stmt, ":pass");
	        sqlite3_bind_text(stmt, idx, password.c_str(), -1, SQLITE_STATIC);

			idx = sqlite3_bind_parameter_index(stmt, ":fn");
	        sqlite3_bind_text(stmt, idx, first_name.c_str(), -1, SQLITE_STATIC);

			idx = sqlite3_bind_parameter_index(stmt, ":mn");
	        sqlite3_bind_text(stmt, idx, middle_name.c_str(), -1, SQLITE_STATIC);

			idx = sqlite3_bind_parameter_index(stmt, ":ln");
	        sqlite3_bind_text(stmt, idx, last_name.c_str(), -1, SQLITE_STATIC);

			idx = sqlite3_bind_parameter_index(stmt, ":mail");
	        sqlite3_bind_text(stmt, idx, email.c_str(), -1, SQLITE_STATIC);

			idx = sqlite3_bind_parameter_index(stmt, ":s");
	        sqlite3_bind_text(stmt, idx, salt.c_str(), -1, SQLITE_STATIC);

            rc = sqlite3_step( stmt );
            if ( rc != SQLITE_DONE ) {
			    std::cerr << "Error" << std::endl; exit ( -1 );
            }

            sqlite3_finalize( stmt );
    }

}
bool Database::progress_procedure(std::string procedure)
{
    switch (get_stage(procedure)) {
    case STAGE_WAITKEYS:
        expire_public_key_timer(procedure);
        break;
    case STAGE_WAITPOLYNOMIAL:
        expire_polynomial_timer(procedure);
        break;
    case STAGE_WAITGETPRIVKEYS:
        expire_secret_key_timer(procedure);
        break;
    case STAGE_VOTING:
        expire_election_timer(procedure);
        break;
    case STAGE_HALT:
        return false;
    default:
        break;
    }

    return true;
}

/**
 * Deletes a procedure.
 */
void Database::delete_procedure(std::string procedure)
{
    int rv, idx;

	sqlite3_stmt *stmt = NULL;
	sqlite3_prepare_v2(db,
            "DELETE FROM is_authority WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM auth_poly WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM auth_g_values WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM proc WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM proc_data WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM choice WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM proc_choice WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM proc_pubkey WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM proc_masterkey WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM cipher_result WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM preresult WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM pubkey WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "DELETE FROM result WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);

}

/**
 * Initialize the database values for the specified procedure.
 * @param proc the procedure ID.
 * @return @b true if successful, @b false otherwise.
 */
 bool Database::start_procedure(std::string procedure)
{
    DEBUG(("DEBUG: Starting procedure %s\n", procedure.c_str()));

	/* Clear the polynomials for this procedure. */

	int rv, idx;

	sqlite3_stmt *stmt = NULL;
	sqlite3_prepare_v2(db,
            "DELETE FROM auth_poly WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Clear the g-values for this procedure. */
	sqlite3_prepare_v2(db,
            "DELETE FROM auth_g_values WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "UPDATE is_authority SET public_key = \"\" WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	sqlite3_prepare_v2(db,
            "UPDATE is_authority SET stage = 0 WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Zero the authority count and set stage for this procedure. */

	sqlite3_prepare_v2(db,
            "UPDATE proc_data SET stage = 1 WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Clear the encrypted choices for this procedure. */
	sqlite3_prepare_v2(db,
            "DELETE FROM choice WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Clear the public keys for this procedure. */
	sqlite3_prepare_v2(db,
            "DELETE FROM proc_pubkey WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;


	/* Clear the encrypted totals for this procedure. */
	sqlite3_prepare_v2(db,
            "DELETE FROM cipher_result WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Clear the partially-decrypted sums for this procedure. */
	sqlite3_prepare_v2(db,
            "DELETE FROM preresult WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Clear the final (plaintext) results for this procedure. */
	sqlite3_prepare_v2(db,
            "DELETE FROM result WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Clear the master public key for this procedure. */
	sqlite3_prepare_v2(db,
            "DELETE FROM pubkey WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;

	/* Update the procedure creation time to the start time. */
	sqlite3_prepare_v2(db,
            "UPDATE proc SET create_time = :t WHERE proc_id = :procid ",
            -1, &stmt, NULL);

	idx = sqlite3_bind_parameter_index(stmt, ":t");
    sqlite3_bind_int(stmt, idx, int(time(0)) );

	idx = sqlite3_bind_parameter_index(stmt, ":procid");
	sqlite3_bind_text(stmt, idx, procedure.c_str(), -1, SQLITE_STATIC);

	if( (rv = sqlite3_step(stmt)) != SQLITE_DONE )
        std::cerr << "Error" << std::endl;

	sqlite3_finalize(stmt);
	stmt = NULL;
/*
    if (get_create_time(procedure) + get_public_key_time(procedure) <= time(0)) {
	set_stage(procedure, STAGE_HALT);
        return true;
    }
*/
    /*PublicKeyTimerHandler* timer = new PublicKeyTimerHandler(get_procedure());
    int timeout = get_public_key_time(procedure);
    ACE_Time_Value initial_delay(timeout);
    ACE_Reactor::instance()->schedule_timer(timer, 0, initial_delay);*/
    set_stage(procedure, STAGE_WAITKEYS);

    return true;

}
